Skip to content

Conversation

dAdAbird
Copy link
Member

@dAdAbird dAdAbird commented Sep 30, 2025

  • The GUC option is applied to all created keys (principal and internal).
  • Hence _keys files (as well as principal keys) may contain keys of different sizes. For that, keys have a "key size" field now (principal key already have had). And tde_aes funcs have a new arg "key size".
  • On server start, we check for old _keys files and rewrite them with the new format (see comments to the related commit and code). However, it doesn't work (it has a bug with decrypting a principal key from the old file). But please review and provide feedback on the general idea.
  • SMGR keys don't work yet.
  • Streaming replication tests fail.
  • I haven't tried key rotation.

This is a draft and needs further improvements and refactoring. I just want feedback on the general direction.

Cheers

It's a draft. Only Principal and WAL keys work so far
@dAdAbird dAdAbird force-pushed the 32_byte_keys_take2 branch from c012cde to 0b8794c Compare October 2, 2025 14:51
Copy link
Collaborator

@artemgavrilov artemgavrilov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good to me

AesEcbEncrypt(EVP_CIPHER_CTX **ctxPtr, const unsigned char *key, int key_len, const unsigned char *in, int in_len, unsigned char *out)
{
int out_len;
const EVP_CIPHER *cipher = key_len == 32 ? cipher_ctr_ecb_256 : cipher_ctr_ecb;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for me it needs better validation here, or may be even accept some enum value here instead of key_len as we always expect discrete values.

NULL /* show_hook */
);

DefineCustomEnumVariable("pg_tde.cipher", /* name */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure that over time we will have request for multi-tenant cipher configuration. Not sure, but maybe it worth to think how to simplify our future. Maybe call it pg_tde.default_cipher?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, I'm not sure. It might be confusing right now - if that's a default then what else could be set. Besides the real default is "aes128" - which is if the GUC isn't defined :)
But a good point, need to think about that

}

void
pg_tde_update_wal_keys_file(void)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something like migrate fits better to this function name rather than update


typedef struct WalKeyFileEntry
{
uint32 key_len;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it's worth to store cipher type here as well for future needs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point.

}
pg_tde_save_server_key(principalKey, false);
TDEXLogSmgrInitWrite(true);
TDEXLogSmgrInitWrite(true, 16);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's pinned here just for time being?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I haven't look at tools yet, so it's a stub just to compile. The basebackup and other (?) tools that creates key, probably would have to have it's own flag for the key size/cipher

It does make sense to rewrite old files on server start (otherwise it'll
slow down random read/write). But reading all _keys files and checking
the magic number could slow the server start, especially if there are
a lot of databases with encrypted tables.  Moreover, we'd rewrite files
once but would have to scan and read them on every start... That's why
this commit introduces new suffixes to the filenames in the new format.
That way, we would only scan the dir and read file names, instead of
opening and reading each _keys file.

typedef struct TDEMapEntry
{
uint32 key_len; /* Part of AAD */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to encode which cipher was used? And do we want to support ciphers with variable IV lengths?

#define PG_TDE_MAP_OLD_FNAME_SUFFIX "_keys"

#define PG_TDE_FILEMAGIC 0x04454454 /* version ID value = TDE 04 */
#define PG_TDE_MAP_FILENAME "%d_keys_v2" /* TODO: should be _v2 of _v4 ? */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't having a different suffix complicate life for tools which work with the files, e.g. pg_basebackup?

/*
* TODO: An ugly hack for now, we need to get a key info when rewriting
* an old file...
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make more sense to have this as a separate function which is called by the migration code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants